import logging
import sys
from pathlib import Path
from datetime import datetime
from typing import Optional

def setup_logger(
    name: str,
    log_file: Optional[str] = None,
    level: int = logging.INFO,
    format_string: Optional[str] = None
) -> logging.Logger:
    """
    Set up a logger with console and file handlers.
    
    Args:
        name: Logger name
        log_file: Path to log file
        level: Logging level
        format_string: Log message format
        
    Returns:
        Configured logger instance
    """
    if format_string is None:
        format_string = '%(asctime)s [%(levelname)s] %(name)s: %(message)s'
        
    formatter = logging.Formatter(format_string)
    
    logger = logging.getLogger(name)
    logger.setLevel(level)
    
    # Remove existing handlers
    logger.handlers = []
    
    # Console handler
    console_handler = logging.StreamHandler(sys.stdout)
    console_handler.setFormatter(formatter)
    logger.addHandler(console_handler)
    
    # File handler
    if log_file:
        file_handler = logging.FileHandler(log_file)
        file_handler.setFormatter(formatter)
        logger.addHandler(file_handler)
        
    return logger

class StrategyLogger:
    """Logger specifically for trading strategies."""
    
    def __init__(
        self,
        strategy_name: str,
        log_dir: Optional[str] = None,
        console_level: int = logging.INFO,
        file_level: int = logging.DEBUG
    ):
        """
        Initialize strategy logger.
        
        Args:
            strategy_name: Name of the strategy
            log_dir: Directory for log files
            console_level: Logging level for console output
            file_level: Logging level for file output
        """
        self.strategy_name = strategy_name
        
        if log_dir is None:
            log_dir = Path(__file__).parent.parent / 'logs' / 'strategies'
            
        self.log_dir = Path(log_dir)
        self.log_dir.mkdir(parents=True, exist_ok=True)
        
        # Create log file name with timestamp
        timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
        log_file = self.log_dir / f"{strategy_name}_{timestamp}.log"
        
        # Set up logger
        self.logger = setup_logger(
            name=f"strategy.{strategy_name}",
            log_file=str(log_file),
            level=min(console_level, file_level)
        )
        
        # Set specific levels for handlers
        self.logger.handlers[0].setLevel(console_level)  # Console handler
        self.logger.handlers[1].setLevel(file_level)     # File handler
        
    def info(self, message: str) -> None:
        """Log info message."""
        self.logger.info(message)
        
    def debug(self, message: str) -> None:
        """Log debug message."""
        self.logger.debug(message)
        
    def warning(self, message: str) -> None:
        """Log warning message."""
        self.logger.warning(message)
        
    def error(self, message: str) -> None:
        """Log error message."""
        self.logger.error(message)
        
    def critical(self, message: str) -> None:
        """Log critical message."""
        self.logger.critical(message)
        
class BacktestLogger(StrategyLogger):
    """Logger specifically for backtesting."""
    
    def __init__(
        self,
        strategy_name: str,
        backtest_id: str,
        log_dir: Optional[str] = None
    ):
        """
        Initialize backtest logger.
        
        Args:
            strategy_name: Name of the strategy
            backtest_id: Unique identifier for the backtest
            log_dir: Directory for log files
        """
        if log_dir is None:
            log_dir = Path(__file__).parent.parent / 'logs' / 'backtests'
            
        super().__init__(
            strategy_name=f"{strategy_name}_backtest_{backtest_id}",
            log_dir=log_dir
        )
        
    def log_trade(self, trade_data: dict) -> None:
        """
        Log trade execution details.
        
        Args:
            trade_data: Dictionary containing trade details
        """
        self.info(
            f"Trade executed: {trade_data['side']} {trade_data['quantity']} "
            f"{trade_data['symbol']} @ {trade_data['price']:.2f}"
        )
        
    def log_portfolio(self, portfolio_data: dict) -> None:
        """
        Log portfolio status.
        
        Args:
            portfolio_data: Dictionary containing portfolio details
        """
        self.debug(
            f"Portfolio value: {portfolio_data['total_value']:.2f}, "
            f"Cash: {portfolio_data['cash']:.2f}"
        )

class ConsoleLogger:
    """Logger that only outputs to console.
    
    from utils.logger import ConsoleLogger
    import logging
    
    # 创建控制台日志记录器
    logger = ConsoleLogger(
        name="MyLogger",
        level=logging.INFO  # 或者使用 logging.DEBUG 查看更详细的日志
    )
    
    # 使用日志记录器
    logger.info("这是一条信息")
    logger.debug("这是一条调试信息")  # 如果级别是 INFO，这条不会显示
    logger.warning("这是一条警告")
    logger.error("这是一条错误信息")
    logger.critical("这是一条严重错误信息")
    
    # 修改日志级别
    logger.set_level(logging.DEBUG)  # 现在可以看到 debug 信息了
    logger.debug("这条调试信息现在可以看到了")"""
    
    def __init__(
        self,
        name: str,
        level: int = logging.INFO,
        format_string: Optional[str] = None
    ):
        """
        Initialize console logger.
        
        Args:
            name: Logger name
            level: Logging level
            format_string: Log message format
        """
        if format_string is None:
            format_string = '%(asctime)s [%(levelname)s] %(name)s: %(message)s'
            
        formatter = logging.Formatter(format_string)
        
        self.logger = logging.getLogger(name)
        self.logger.setLevel(level)
        
        # Remove existing handlers
        self.logger.handlers = []
        
        # Console handler
        console_handler = logging.StreamHandler(sys.stdout)
        console_handler.setFormatter(formatter)
        console_handler.setLevel(level)
        self.logger.addHandler(console_handler)
        
    def info(self, message: str) -> None:
        """Log info message."""
        self.logger.info(message)
        
    def debug(self, message: str) -> None:
        """Log debug message."""
        self.logger.debug(message)
        
    def warning(self, message: str) -> None:
        """Log warning message."""
        self.logger.warning(message)
        
    def error(self, message: str) -> None:
        """Log error message."""
        self.logger.error(message)
        
    def critical(self, message: str) -> None:
        """Log critical message."""
        self.logger.critical(message)
        
    def set_level(self, level: int) -> None:
        """
        Set logging level.
        
        Args:
            level: New logging level
        """
        self.logger.setLevel(level)
        self.logger.handlers[0].setLevel(level)
